<!DOCTYPE html>
<html>
<head>
<title>sdp对不同类型产品的支持</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
/* GitHub stylesheet for MarkdownPad (http://markdownpad.com) */
/* Author: Nicolas Hery - http://nicolashery.com */
/* Version: b13fe65ca28d2e568c6ed5d7f06581183df8f2ff */
/* Source: https://github.com/nicolahery/markdownpad-github */

/* RESET
=============================================================================*/

html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video {
  margin: 0;
  padding: 0;
  border: 0;
}

/* BODY
=============================================================================*/

body {
  font-family: Helvetica, arial, freesans, clean, sans-serif;
  font-size: 14px;
  line-height: 1.6;
  color: #333;
  background-color: #fff;
  padding: 20px;
  max-width: 960px;
  margin: 0 auto;
}

body>*:first-child {
  margin-top: 0 !important;
}

body>*:last-child {
  margin-bottom: 0 !important;
}

/* BLOCKS
=============================================================================*/

p, blockquote, ul, ol, dl, table, pre {
  margin: 15px 0;
}

/* HEADERS
=============================================================================*/

h1, h2, h3, h4, h5, h6 {
  margin: 20px 0 10px;
  padding: 0;
  font-weight: bold;
  -webkit-font-smoothing: antialiased;
}

h1 tt, h1 code, h2 tt, h2 code, h3 tt, h3 code, h4 tt, h4 code, h5 tt, h5 code, h6 tt, h6 code {
  font-size: inherit;
}

h1 {
  font-size: 28px;
  color: #000;
}

h2 {
  font-size: 24px;
  border-bottom: 1px solid #ccc;
  color: #000;
}

h3 {
  font-size: 18px;
}

h4 {
  font-size: 16px;
}

h5 {
  font-size: 14px;
}

h6 {
  color: #777;
  font-size: 14px;
}

body>h2:first-child, body>h1:first-child, body>h1:first-child+h2, body>h3:first-child, body>h4:first-child, body>h5:first-child, body>h6:first-child {
  margin-top: 0;
  padding-top: 0;
}

a:first-child h1, a:first-child h2, a:first-child h3, a:first-child h4, a:first-child h5, a:first-child h6 {
  margin-top: 0;
  padding-top: 0;
}

h1+p, h2+p, h3+p, h4+p, h5+p, h6+p {
  margin-top: 10px;
}

/* LINKS
=============================================================================*/

a {
  color: #4183C4;
  text-decoration: none;
}

a:hover {
  text-decoration: underline;
}

/* LISTS
=============================================================================*/

ul, ol {
  padding-left: 30px;
}

ul li > :first-child, 
ol li > :first-child, 
ul li ul:first-of-type, 
ol li ol:first-of-type, 
ul li ol:first-of-type, 
ol li ul:first-of-type {
  margin-top: 0px;
}

ul ul, ul ol, ol ol, ol ul {
  margin-bottom: 0;
}

dl {
  padding: 0;
}

dl dt {
  font-size: 14px;
  font-weight: bold;
  font-style: italic;
  padding: 0;
  margin: 15px 0 5px;
}

dl dt:first-child {
  padding: 0;
}

dl dt>:first-child {
  margin-top: 0px;
}

dl dt>:last-child {
  margin-bottom: 0px;
}

dl dd {
  margin: 0 0 15px;
  padding: 0 15px;
}

dl dd>:first-child {
  margin-top: 0px;
}

dl dd>:last-child {
  margin-bottom: 0px;
}

/* CODE
=============================================================================*/

pre, code, tt {
  font-size: 12px;
  font-family: Consolas, "Liberation Mono", Courier, monospace;
}

code, tt {
  margin: 0 0px;
  padding: 0px 0px;
  white-space: nowrap;
  border: 1px solid #eaeaea;
  background-color: #f8f8f8;
  border-radius: 3px;
}

pre>code {
  margin: 0;
  padding: 0;
  white-space: pre;
  border: none;
  background: transparent;
}

pre {
  background-color: #f8f8f8;
  border: 1px solid #ccc;
  font-size: 13px;
  line-height: 19px;
  overflow: auto;
  padding: 6px 10px;
  border-radius: 3px;
}

pre code, pre tt {
  background-color: transparent;
  border: none;
}

kbd {
    -moz-border-bottom-colors: none;
    -moz-border-left-colors: none;
    -moz-border-right-colors: none;
    -moz-border-top-colors: none;
    background-color: #DDDDDD;
    background-image: linear-gradient(#F1F1F1, #DDDDDD);
    background-repeat: repeat-x;
    border-color: #DDDDDD #CCCCCC #CCCCCC #DDDDDD;
    border-image: none;
    border-radius: 2px 2px 2px 2px;
    border-style: solid;
    border-width: 1px;
    font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
    line-height: 10px;
    padding: 1px 4px;
}

/* QUOTES
=============================================================================*/

blockquote {
  border-left: 4px solid #DDD;
  padding: 0 15px;
  color: #777;
}

blockquote>:first-child {
  margin-top: 0px;
}

blockquote>:last-child {
  margin-bottom: 0px;
}

/* HORIZONTAL RULES
=============================================================================*/

hr {
  clear: both;
  margin: 15px 0;
  height: 0px;
  overflow: hidden;
  border: none;
  background: transparent;
  border-bottom: 4px solid #ddd;
  padding: 0;
}

/* TABLES
=============================================================================*/

table th {
  font-weight: bold;
}

table th, table td {
  border: 1px solid #ccc;
  padding: 6px 13px;
}

table tr {
  border-top: 1px solid #ccc;
  background-color: #fff;
}

table tr:nth-child(2n) {
  background-color: #f8f8f8;
}

/* IMAGES
=============================================================================*/

img {
  max-width: 100%
}
</style>
</head>
<body>
<h2>SDP对不同类型产品支持</h2>
<blockquote>
<p>sdp目前支持Nectar产品、mk产品、abrazos产品、移动插件产品，eme产品，Enzyme插件产品。本文档从产品构建过程和构建结果处理几个方面详细介绍sdp对不同类型产品的支持情况。	</p>
</blockquote>
<h3>构建过程介绍</h3>
<p>不同类型的产品构建过程不尽相同，但是构建的整体流程是确定的。
产品构建在流程上可以分为以下几个阶段：</p>
<ol>
<li>
<p>检查用户是否可以发起构建</p>
<pre><code>包括两方面的检查：
    检查用户角色 - 只有管理员及以上权限才可发起构建
    检查构建间隔 - 只有用户距上次构建的间隔大于用户能力中限制的时间间隔才可发起构建
</code></pre>

</li>
<li>
<p>准备构建数据</p>
<pre><code>获取构建配置中产品配置信息
</code></pre>

</li>
<li>
<p>根据构建服务的要求准备构建工作空间、工程、依赖等</p>
</li>
<li>
<p>通知构建服务发起构建</p>
<pre><code>对于第三方构建服务，需要通过发送请求通知构建服务开始构建（如mk、abrazos、移动应用和mdp构建）
有些构建没有构建服务（直接由sdp.server完成构建，如enzyme插件，移动插件，eme类型构建）则不需要通知。 
</code></pre>

</li>
<li>
<p>buildMonitor查询构建是否完成</p>
<pre><code>sdp.server启动时，monitor启动，当构建队列中存在状态处于“building”的构建时，monitor开始定时检查构建状态，不断调用对应构建类型的tryComplete，
当构建完成后，构建类型调用自己的complete方法完成后续构建结果处理
</code></pre>

</li>
<li>
<p>构建完成后下载构建结果，修改构建状态为“完成”，保存产品信息</p>
<pre><code>构建完成后，sdp.server会从构建服务中获取构建结果，存放在产品仓库中，并且增加产品记录（记录产品的信息，以及产品存放位置）
</code></pre>

</li>
</ol>
<p>在以上过程中，步骤3、4、6根据构建类型不同有所不同，其他的过程基本一致。</p>
<h3>Nectar产品</h3>
<blockquote>
<h4>移动应用产品</h4>
</blockquote>
<pre><code>移动类型的产品比较特殊，在产品配置中选择工程时，需要解析工程目录下app.config文件获取应用信息，包括：
    {
        &quot;app_name&quot;: 应用名称,
        &quot;appId&quot;: 应用id,
        &quot;description&quot;: 应用描述,
        &quot;app_project_id&quot;: 应用对应工程id,
        &quot;version&quot;: 应用版本 //发布时，需要用户填写应用版本号，版本号分三段，其中前两段就是从这里读取
    }

用户在移动应用管理平台创建应用时需要绑定产品配置，绑定后产品配置不能再被删除，需要用户在应用管理平台解绑后才可删除。
</code></pre>

<ul>
<li>
<p><strong>构建过程</strong></p>
<ol>
<li>
<p>准备构建数据</p>
<pre><code>获取构建配置中产品配置的具体信息，从中可以获得待构建的工程       
在构建配置信息的extend_info字段中，可以获取本次构建的类型（iOS/android）和构建所用证书
</code></pre>

</li>
<li>
<p>准备工程和插件</p>
<pre><code>首先在master_workspace中将develop分支合并到master，然后拉取master分支
然后根据步骤1中获取到的产品配置信息找到待构建的工程
读取工程中carrier目录下的carrier.config文件并解析，获取工程中使用的移动插件列表：RN_plugins
获取项目依赖列表：dependencies
遍历RN_plugins，如果有插件不在dependencies中，抛出构建异常
针对RN_plugins中的每一个插件，项store查询是否可用，如果查询出错，或者插件不可用，或者未查找到商品，均抛出构建异常
插件检查完毕后，检查插件是否在本地仓库中有缓存，如果没有缓存，需要从store下载插件
下载完毕后，工程和插件准备完成
</code></pre>

</li>
<li>
<p>准备构建工作空间</p>
<pre><code>移动构建的构建服务在单独的服务器上，而且iOS和android分别在不同的构建服务器。 
在步骤1中，获取构建类型后，可以确定构建服务器的地址：builder_url
发起构建前，需要先向builder请求一个构建工作空间
请求返回spaceID
</code></pre>

</li>
<li>
<p>准备工程和插件，上传至构建服务器</p>
<pre><code>向构建服务器请求构建工作空间完成后，需要把待构建的插件和工程上传到构建工作空间中
首先创建一个临时目录temp_dir，然后将2步骤中准备好的插件解压（两次解压）至temp_dir/plugins/RN中
然后把工程copy到temp_dir下
把temp_dir压缩倒临时创建的upload_temp目录下，压缩文件命名为“project.zip”
把project.zip上传至步骤3中申请的space中
</code></pre>

</li>
<li>
<p>检查证书并发送给构建服务器</p>
<pre><code>根据构建类型，需要上传的证书不同，android构建需要上传keystore文件，iOS构建需要上传p12证书和provision证书
</code></pre>

</li>
<li>
<p>准备构建信息文件：build_info.json，并上传至构建服务器</p>
<pre><code>根据构建信息，生成构建信息文件，格式如下：
    {
        &quot;sign_info&quot;: {
            &quot;android&quot;: {
                &quot;isBuild&quot;: 是否进行安卓构建,
                &quot;isDefault&quot;: 是否默认,
                &quot;keystoreFilename&quot;: keystore文件名,
                &quot;keystorePassword&quot;: KeyStore密码
            },
            &quot;ios&quot;: {
                &quot;isDefault&quot;: 是否默认,
                &quot;isBuild&quot;: 是否进行iOS构建,
                &quot;p12Filename&quot;: p12证书文件名,
                &quot;p12Password&quot;: p12Password ,
                &quot;ppID&quot;: provision id,
                &quot;ppFilename&quot;: provision文件名
            }
        },
        &quot;isDebug&quot;: 是否是调试模式(只有mdp构建时，此处为true)
    };

上传文件至构建服务器
</code></pre>

</li>
<li>
<p>调用构建服务接口，发起构建</p>
<pre><code>根据不同类型（android/iOS）, 向不同的构建服务发送请求，开始构建
</code></pre>

</li>
<li>
<p>buildMonitor查询构建是否完成</p>
</li>
<li>构建完成后下载构建结果，设置构建状态，保存产品信息</li>
</ol>
</li>
<li>
<p><strong>构建结果处理</strong></p>
<p>移动应用的构建结果不会经过store流转，而是上传至移动应用管理平台。
构建完成后，在构建结果管理页面，app类型的构建后边会有上传按钮，点击上传按钮，填写信息，开始把移动应用发布到应用管理平台。过程如下：</p>
<ol>
<li>获取信息（包括构建信息，构建配置信息， 产品配置信息）</li>
<li>根据构建类型（应用类型,iOS或android）创建对应的版本</li>
<li>获取应用文件。根据build_ id获取对应的product, 解压后拿到应用文件：apk或ipa文件</li>
<li>将文件上传至移动应用管理平台。</li>
</ol>
</li>
</ul>
<blockquote>
<h4>MDP产品</h4>
</blockquote>
<ul>
<li>
<p><strong>构建过程</strong></p>
<p>MDP产品构建过程和移动应用产品构建基本一致。不同点如下：</p>
<ol>
<li>
<p>在准备工程和插件过程中，MDP产品的工程不完全从工作空间中获取，而是由两部分组成：Nectar团队开发的mdp核心代码和用户自己开发的代码。其中mdp核心代码存放在Nectar提供的一个git库下，准备工程时，需要从该git库下拉取代码，将jsx 和 img目录放在web目录下，然后放到工程目录。然后，MDP产品有一些必要的插件也是放在mdp核心代码库中plugins目录下的。在准备插件时，需要将该目录下的插件copy到工程中的插件目录下，然后修改carrier.config文件中的插件描述。最后调用Nectar提供的方法修改工程中的app.config文件。至此，MDP工程和插件准备完毕</p>
</li>
<li>
<p>在准备构建信息文件：build_info.json时，isDebug字段为true.</p>
</li>
</ol>
</li>
<li>
<p><strong>构建结果处理</strong></p>
<p>MDP自定义构建的结果可以直接从sdp下载</p>
</li>
</ul>
<blockquote>
<h4>移动插件产品</h4>
</blockquote>
<ul>
<li>
<p><strong>构建过程</strong></p>
<ol>
<li>
<p>准备构建数据</p>
<p>获取构建配置中产品配置的具体信息，从中可以获得待构建的移动插件工程</p>
</li>
<li>
<p>准备插件工程源码</p>
<p>将master<em>workspace中对应的git库合并，拉取之后，根据产品配置后去插件工程源码，并copy到一个临时目录下		
从产品配置的detail字段读取“resource</em>publication”的值（插件是否公开源码）,生成plugin_publication.xml文件，放在插件工程目录中</p>
</li>
<li>
<p>开始构建</p>
<p>移动插件构建过程就是将源码压缩为zip包的过程。</p>
</li>
<li>
<p>buildMonitor查询构建是否完成</p>
<p>移动插件类型的构建没有实现tryComplete方法。在步骤3中构建完成后直接将构建状态改成“completed”</p>
</li>
<li>
<p>构建完成后下载构建结果，设置构建状态，保存产品信息</p>
<p>将移动插件源码的压缩包copy到产品仓库中，修改构建状态为“success”，保存产品信息，构建完成</p>
</li>
</ol>
</li>
<li>
<p><strong>构建结果处理</strong></p>
<p>移动插件产品需要发布到store中，以依赖的形式添加到sdp项目中,然后以软链接的方式将依赖更新到工作空间中供nectar开发者使用。
商品发布的流程在“sdp中商品流转过程”文档中有描述，这里只讲述发布前准备商品文件的过程。</p>
<p>移动插件类型产品在发布前有两次压缩：</p>
<pre><code>1. 将找到的构建结果，解压到临时目录temp_ dir中，然后移动到temp_ dir/nectar_plugin 下，并重命名为：插件name + '_' + 插件版本
2. 将temp_ dir/nectar_plugin 添加到压缩文件 temp_ dir/nectar_plugin.zip（第一次压缩）
3. 删除temp_ dir/nectar_plugin目录，然后将temp_ dir/nectar_plugin.zip压缩到config.sdp_dir.publish_temp/商品名 + '.zip'（第二次压缩，为了支持一个插件商品中包含多个插件）
</code></pre>

<p>至此，商品文件准备完毕。</p>
</li>
</ul>
<h3>mk产品</h3>
<ul>
<li>
<h4>mk_product产品</h4>
</li>
<li>
<h4>mk_feature产品</h4>
</li>
</ul>
<h3>abrazos产品</h3>
<ul>
<li>
<p><strong>构建过程</strong></p>
<ol>
<li>
<p>准备构建数据</p>
<p>获取工程信息，产品配置信息， 构建配置信息</p>
</li>
<li>
<p>准备构建工作空间</p>
<p>abrazos类型的构建需要为其准备一个构建用的工作空间，然后将代码和依赖的商品放在构建工作空间中。</p>
<ul>
<li>从master_ workspace中合并分支，拉取分支，获取最新代码</li>
<li>检查 build_ workspace是否已经存在，不存在创建出来。build_ workspace命名：project.namespace + '-' + project.name </li>
<li>将产品配置中选择的工程copy到build_workspace下的source目录下</li>
<li>准备依赖。abrazos产品构建需要依赖core_ node，检查core_ node是否可用（检查项目依赖中是否有core_ node,然后向store发请求查询core_ node的添加者是否能使用core_ node),检查可用后将core_ node复制到build_ workspace下target目录中</li>
</ul>
<p>至此构建工作空间准备完毕</p>
</li>
<li>
<p>向构建服务发送请求，开始执行构建</p>
</li>
<li>
<p>buildMonitor查询构建是否完成</p>
<p>查询时，调用构建服务提供的查询接口获取构建进度。各个类型的构建都有构建超时时间，超时认为构建失败	</p>
</li>
<li>
<p>构建完成后下载构建结果，设置构建状态，保存产品信息</p>
</li>
</ol>
</li>
<li>
<p><strong>构建结果处理</strong></p>
<p>abrazos产品构建完成后可以直接在构建结果列表中下载</p>
</li>
</ul>
<h3>eme产品/Enzyme插件产品</h3>
<ul>
<li>
<p><strong>构建过程</strong></p>
<p>这两种类型的产品没有单独的构建服务，构建过程就是根据产品配置中选择的工程或eme文件，然后压缩为zip(同移动插件产品构建过程)</p>
<pre><code>不同的是，eme文件和enzyme工程类型产品的产品配置中选择eme文件（或选择工程）时都可以选择多个。
</code></pre>

</li>
<li>
<p><strong>构建结果处理</strong></p>
</li>
</ul>

</body>
</html>
<!-- This document was created with MarkdownPad, the Markdown editor for Windows (http://markdownpad.com) -->
